#if defined(WIN32)
#include <windows.h>
#endif  // OS
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "DBOption/Mysql/MysqlResult.h"
#include "DBOption/Mysql/MysqlConnector.h"
#include "base/core/com_define.h"
#include "base/core/char_operation.h"

MySqlRow::MySqlRow()
	: m_fieldCount(0),
	m_queryRow(nullptr),
	m_fieldLength(nullptr) 
{}

MySqlRow::MySqlRow(MYSQL_RES* mysqlResult, int filedCount)
	: m_fieldCount(filedCount),
	m_queryRow(nullptr) ,
	m_fieldLength(nullptr) 
{
    m_queryRow = mysql_fetch_row(mysqlResult);
    m_fieldLength = mysql_fetch_lengths(mysqlResult);
}

MySqlRow::~MySqlRow() 
{
    m_fieldCount  = 0;
    m_fieldLength = nullptr;
    m_queryRow    = nullptr;
}

bool MySqlRow::IsValid() 
{
    return m_queryRow != nullptr;
}

bool  MySqlRow::GetInt(int fileld, int& value) 
{
    if (!IsLegalNumberFileld(fileld)) 
	{
        return false;
    }
    value = static_cast<int>(atoi(m_queryRow[fileld]));
    return true;
}

bool  MySqlRow::GetUint(int fileld, uint32_t& value)
{
    if (!IsLegalNumberFileld(fileld)) 
	{
        return false;
    }
    value = static_cast<uint32_t>(strtoul(m_queryRow[fileld], nullptr, 10));
    return true;
}

bool MySqlRow::GetInt64(int fileld, int64_t& value) 
{
    if (!IsLegalNumberFileld(fileld)) 
	{
        return false;
    }
    value = static_cast<int64_t>(strtoull(m_queryRow[fileld], nullptr, 10));
    return true;
}

bool MySqlRow::GetUInt64(int fileld, uint64_t& value) 
{
    if (!IsLegalNumberFileld(fileld))
	{
        return false;
    }
    value = static_cast<uint64_t>(strtoull(m_queryRow[fileld], nullptr, 10));
    return true;
}

bool  MySqlRow::GetFloat(int fileld, float& value) 
{
    if (!IsLegalNumberFileld(fileld))
	{
        return false;
    }
    value = static_cast<float>(atof(m_queryRow[fileld]));
    return true;
}

bool  MySqlRow::GetUchar(int fileld, uint8_t& value) 
{
    if (!IsLegalNumberFileld(fileld)) 
	{
        return false;
    }
    value = static_cast<uint8_t>(atoi(m_queryRow[fileld]));
    return true;
}

bool  MySqlRow::GetShort(int fileld, short& value) 
{
    if (!IsLegalNumberFileld(fileld)) 
	{
        return false;
    }
    value = static_cast<short>(atoi(m_queryRow[fileld]));
    return true;
}

bool  MySqlRow::GetUshort(int fileld, uint16_t& value) 
{
    if (!IsLegalNumberFileld(fileld))
	{
        return false;
    }
    value = static_cast<uint16_t>(atoi(m_queryRow[fileld]));
    return true;
}

bool  MySqlRow::GetString(int fileld, char* buf, uint32_t bufSize) 
{
    bool result  = false;
    bool retCode = false;

    if (buf == nullptr) 
	{
        return false;
    }
    if (fileld >= m_fieldCount) 
	{
        return false;
    }
    if (m_queryRow == nullptr) 
	{
        return false;
    }
    if (m_queryRow[fileld] == nullptr) 
	{
        return false;
    }
    if (bufSize < m_fieldLength[fileld] + 1) 
	{
        return false;
    }
    retCode = SafeCopyString(buf, bufSize, m_queryRow[fileld]);
    MMOLOG_PROCESS_ERROR(retCode);
    buf[m_fieldLength[fileld]] = '\0';
    result = true;
Exit0:
    return result;
}

bool  MySqlRow::GetBinary(int fileld, char* Buf, uint32_t BufSize, uint32_t& Length) 
{
    if (fileld >= m_fieldCount) 
	{
        return false;
    }
    if (m_queryRow == nullptr) 
	{
        return false;
    }
    if (m_queryRow[fileld] == nullptr) 
	{
        return false;
    }
    Length = m_fieldLength[fileld];
    if (Buf == nullptr) 
	{
        return false;
    }
    if (BufSize < m_fieldLength[fileld])
	{
        return false;
    }
    memcpy(Buf, m_queryRow[fileld], Length);
    return true;
}

int MySqlRow::GetFieldCount() 
{
    return m_fieldCount;
}

int MySqlRow::GetFieldLength(int fileld) 
{
    if (fileld >= m_fieldCount) 
	{
        return -1;
    }
    if (m_queryRow == nullptr) 
	{
        return -1;
    }
    if (m_queryRow[fileld] == nullptr) 
	{
        return -1;
    }
    return (int)m_fieldLength[fileld];
}

MySqlResult::MySqlResult()
	: m_mysqlRes(nullptr)
	,m_fieldCount(0)
	,m_affectedRows(0)
{}

MySqlResult::MySqlResult(MYSQL_RES* mysqlResult, int affectedRows)
	: m_mysqlRes(nullptr)
	,m_fieldCount(0)
	,m_affectedRows(0) 
{
    SetMySqlResult(mysqlResult, affectedRows);
}

bool MySqlResult::FetchResult(MysqlConnector* connector) 
{
    bool result = false;
    bool retCode = false;

    MMOLOG_ASSERT_EXIT(connector != nullptr);
    retCode = SetMySqlResult(connector->GetQueryResult(), connector->GetAffectedRows());
    MMO_PROCESS_ERROR(retCode);
    result = true;
Exit0:
    return result;
}

bool MySqlResult::SetMySqlResult(MYSQL_RES* mysqlResult, int affectedRows) 
{
    Release();
    m_mysqlRes = mysqlResult;
    m_affectedRows = affectedRows;
    if (m_mysqlRes != nullptr) 
	{
        m_fieldCount = mysql_num_fields(m_mysqlRes);
    }
    return m_mysqlRes != nullptr;
}

bool MySqlResult::Release() 
{
    if (m_mysqlRes != nullptr) 
	{
        mysql_free_result(m_mysqlRes);
        m_mysqlRes = nullptr;
    }
    return true;
}
